#ifndef tContainer_t_H_
#define tContainer_t_H_
#include <algorithm>
#include <iostream>
using namespace std;

template <typename T, class C>
class tContainer_t {
public:
	tContainer_t() {} //Default constructor

	tContainer_t(const tContainer_t& c) {
		copyAllFrom(c);
	}

	virtual ~tContainer_t() {} // Destructor

	/*Operators Overloading*/
	const tContainer_t& operator=(const tContainer_t& c) {
		m_container.clear();
		copyAllFrom(c);
		return *this;
	}
	
	// assign[]
	T*& operator[](unsigned index){
		iter_t iter = m_container.begin();
		if (index < 0 || index >= m_container.size()){
			throw "ERROR: index is out of bounds";
		}

		for (unsigned i = 0 ; i < index; i++, iter++);

		return *iter;
	}

	tContainer_t& operator+=(tContainer_t& c){
		while (c.getNumOfElem()) {
			m_container.push_back(c.getFirstElem());
			c.removeElem(*c.getFirstElem());
		}
		return *this;
	} 


	bool isEmpty() const {
		return m_container.empty();
	}

	int getNumOfElem() const {
		return m_container.size();
	}

	T* getFirstElem() const {
		return isEmpty() ? 0 : m_container.front();
	}

	T* getLastElem() const {
		return isEmpty() ? 0 : m_container.back();
		cout << "";
	}

	T* find(const T& val) const {
		const_iter_t it;
		it = getIterator(val);

		return (it != m_container.end() ? *it : 0);
	}

	void insert(T* elem) {
		m_container.push_back(elem);
	}


	T* removeElem(const T& val) {
		const_iter_t it;

		it = getIterator(val);
		if (it == m_container.end())
			return 0;

		T* retElem = *it;
		m_container.erase(it);

		return retElem;
	}

	void removeAll() {
		m_container.erase(m_container.begin(), m_container.end());
	}

private:
	typedef typename C::iterator iter_t;
	typedef typename C::const_iterator const_iter_t;
	C m_container;

	void copyAllFrom(const tContainer_t& from) {
		const_iter_t it = from.m_container.begin();

		while (it != from.m_container.end()) {
			m_container.push_back(*it);
			it++;
		}
	}

	// Returns an iterator to the first element in the range, for which applying isEqual to it, is true.
	const_iter_t getIterator(const T& elem) const {
		return find_if(m_container.begin(), m_container.end(), isEqual(elem));
	}

	//class isEqual acts as a predicate for the find_if algorithm
	class isEqual {
	public:
		isEqual(T v) : value(v) {}

		bool operator() (T* elem) const { 
			return (*elem == value); 
		}
	private:
		T value;
	}; 
};
#endif /*tContainer_t_H_*/
